﻿using System.Drawing;
using System.Windows.Forms;
using SdmxMl.Common;
using SdmxMl.GenericData;
using SdmxMl.Structure;
using SdmxMl.Manager;
using System.Data;

namespace SdmxMl.UC
{
    public class GroupSerieAttrib
    {
        int defComboWidth = 60;

        protected void GenerateEditControl(Panel panelBack, int curHeight, int editXPos, 
            ISdmxArtefactRef conceptSchemeRef, string conceptId, ISdmxArtefactRef codelistRef, bool isKey)
        {
            
            // The Label
            Label lbl = new Label();
            lbl.Text = conceptId + ":";
            if (isKey)
                lbl.Font = new Font(lbl.Font, FontStyle.Bold);

            lbl.Location = new Point(4, curHeight+2);
            panelBack.Controls.Add(lbl);
 
            // The Editor
            TextBox editCtrl = null; ;
            ConceptType concept = ReferenceManager.LocateConcept(conceptSchemeRef, conceptId);
            CodeListType codeList = null;
            
            // Concept available or not
            if (concept == null)
            {
                editCtrl = new TextBox();
                editCtrl.Location = new Point(editXPos, curHeight);
                editCtrl.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
                editCtrl.Width = panelBack.Width - editXPos - 2;
                panelBack.Controls.Add(editCtrl);
            }
            else
            {
                // Usage of codelist from dimension or from concept (if any)
                if (codelistRef != null && codelistRef.Id.Length > 0)
                    codeList = ReferenceManager.LocateCodelist(codelistRef);
                if (codelistRef == null && concept.CoreRepresentation.Id.Length > 0)
                    codeList = ReferenceManager.LocateCodelist(concept.CoreRepresentation);

                if (codeList != null)
                {
                    MultiColumnComboBox multiCombo = new MultiColumnComboBox();
                    TextBox txCodeInfo = new TextBox();
                    txCodeInfo.Location = new Point(4 + editXPos + defComboWidth, curHeight);
                    txCodeInfo.Width = panelBack.Width - txCodeInfo.Location.X - 2;
                    txCodeInfo.ReadOnly = true;
                    txCodeInfo.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;


                    multiCombo.AutoComplete = false;
                    multiCombo.AutoDropdown = false;
                    multiCombo.BackColorEven = System.Drawing.Color.White;
                    multiCombo.BackColorOdd = System.Drawing.Color.WhiteSmoke;
                    multiCombo.ColumnWidthDefault = 108;
                    multiCombo.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable;
                    multiCombo.FormattingEnabled = true;
                    multiCombo.LinkedColumnIndex = 1;
                    multiCombo.LinkedTextBox = txCodeInfo;
                    multiCombo.Location = new Point(editXPos, curHeight);
                    multiCombo.Name = conceptId;
                    multiCombo.TabIndex = 1;
                    multiCombo.ValueMember = "Code";
                    multiCombo.DisplayMember = "Code";
                    multiCombo.ColumnNames = "Code;Description";
                    multiCombo.DataSource = codeList.CodeList.GetTableRepresentation();
                    multiCombo.Width = defComboWidth;
                    multiCombo.ColumnWidths = (multiCombo.Width / 2).ToString() + ";" + txCodeInfo.Width.ToString();
                    multiCombo.Text = null;
                    multiCombo.DropDownWidth = multiCombo.Width + txCodeInfo.Width;


                    panelBack.Controls.Add(multiCombo);
                    panelBack.Controls.Add(txCodeInfo);
                    multiCombo.Text = null;


                }
                else
                {
                    editCtrl = new TextBox();
                    editCtrl.Location = new Point(editXPos, curHeight);
                    // Get type

                    editCtrl.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
                    editCtrl.Width = panelBack.Width - editXPos - 2;
                    panelBack.Controls.Add(editCtrl);
                }
                // Numeric ?
            }

        }

        /// <summary>
        /// Creates controls and then set value to them.
        /// </summary>
        /// <param name="panelBack"></param>
        /// <param name="dataset"></param>
        /// <param name="group"></param>
        public void FillGroupEditControls(Panel panelBack, DataSetType dataset, DataGroupType group)
        {
            KeyFamilyType dsd = ReferenceManager.LocateDsd(dataset);

            panelBack.Controls.Clear();

            if (dsd != null)
            {
                GroupType grp = dsd.GroupList.GetGroupById(group.Type);
                if (grp != null)
                {
                    InitialiseGroupControls(panelBack, dsd, grp);

                    foreach (ValueType v in group.GroupKey)
                    {
                        Control[] arrC = panelBack.Controls.Find(v.Concept, false);
                        if (arrC.Length == 1)
                        {
                            arrC[0].Text = v.Value;
                        }

                    }

                    foreach (ValueType v in group.Attributes)
                    {
                        Control[] arrC = panelBack.Controls.Find(v.Concept, false);
                        if (arrC.Length == 1)
                        {
                            arrC[0].Text = v.Value;
                        }

                    }

                }
            }

        }

        protected void InitialiseGroupControls(Panel panelBack, KeyFamilyType dsd, GroupType grp)
        {
            int edXLoc = 120;
            ISdmxArtefactRef conceptSchemeRef = null;
            ISdmxArtefactRef codelistRef = null;


            ArtefactList ConceptSchemeList = ReferenceManager.GetArtefactList(SdmxArtefactType.Concepts);
            int curHeight = 4;
            
            // Keys of group
            foreach (string conceptName in grp.DimensionRefList)
            {
                // get dim
                BaseDimensionType dim = dsd.DimensionList.GetDimensionFromName(conceptName);
                conceptSchemeRef = null;
                codelistRef = null;
                if (dim != null)
                {
                    conceptSchemeRef = dim.ConceptSchemeInfo;
                    codelistRef = dim.CodelistInfo;
                }

                GenerateEditControl(panelBack, curHeight, edXLoc, conceptSchemeRef, conceptName, codelistRef, true);
                curHeight += 26;

            }

            // Attrib of group
            foreach (AttributeType a in dsd.AttributeList)
            {
                if (a.AttachmentLevel == AttributeType.AttachmentLevelType.Group &&
                    a.AttachmentGroupList.Contains(grp.Id))
                {
                    conceptSchemeRef = a.ConceptSchemeInfo;
                    codelistRef = a.CodelistInfo;
                    GenerateEditControl(panelBack, curHeight, edXLoc, conceptSchemeRef, a.ConceptInfo.Id, codelistRef, false);
                    curHeight += 26;
                }
            }

        }

        public DataTable ConstructSeriesDataTable(DataSetType dataset, SeriesTypeList seriesList)
        {
            DataTable t = new DataTable("Series");

            KeyFamilyType dsd = ReferenceManager.LocateDsd(dataset);
            if (dsd != null)
            {

                foreach (BaseDimensionType dim in dsd.DimensionList)
                {
                    // Todo: determine some types ?
                    t.Columns.Add(new DataColumn(dim.ConceptInfo.Id, typeof(string)));
                }

                // And Attributes of serie
                // Attrib of group
                foreach (AttributeType a in dsd.AttributeList)
                {
                    if (a.AttachmentLevel == AttributeType.AttachmentLevelType.Series)
                        t.Columns.Add(new DataColumn(a.ConceptInfo.Id, typeof(string)));
                }

                foreach (SeriesType s in seriesList)
                {
                    DataRow row = t.NewRow();
                    foreach (ValueType v in s.SeriesKey)
                        row[v.Concept] = v.Value;
                    foreach (ValueType v in s.Attributes)
                        row[v.Concept] = v.Value;
                    t.Rows.Add(row);
                }
            }

            return t;
        }

        public DataTable ConstructObjDataTable(DataSetType dataset, ObsTypeList obsList)
        {
            DataTable t = new DataTable();

            KeyFamilyType dsd = ReferenceManager.LocateDsd(dataset);
            if (dsd != null)
            {
                TimeDimensionType td = dsd.DimensionList.GetTimeDimension();
                //TODO: What todo ?
                if (td == null)
                    td = new TimeDimensionType();
                t.Columns.Add(new DataColumn(td.ConceptInfo.Id, typeof(string)));
                t.Columns.Add(new DataColumn("ObsValue", typeof(string)));

                // And Attributes of serie
                // Attrib of group
                foreach (AttributeType a in dsd.AttributeList)
                {
                    if (a.AttachmentLevel == AttributeType.AttachmentLevelType.Observation)
                        t.Columns.Add(new DataColumn(a.ConceptInfo.Id, typeof(string)));
                }

                foreach (ObsType obs in obsList)
                {
                    DataRow row = t.NewRow();
                    row[0] = obs.Time.ToString();
                    row[1] = obs.ObsValue.Value;
                    foreach (ValueType v in obs.Attributes)
                        row[v.Concept] = v.Value;
                    t.Rows.Add(row);
                }

            }

            return t;
        }


    }
}
